/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package testing_class;

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketException;
import java.net.UnknownHostException;
import java.util.Random;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 *
 * @author minaev
 */
public class UDP_Fluder extends Thread {

    DatagramSocket ds;
    DatagramPacket dp, dp_sts;
    byte id = 0;
    long ms_delay;
    boolean process = true;
    int dt1, dt2, dt3, pos = 0;
    byte sbuf[] = new byte[11];
    byte sbuf_sts[] = new byte[6];
    long cnt_send = 0;
    long cnt_send_sts = 0;
    Random r = new Random();

    public UDP_Fluder(String host, long ms_delay)
            throws SocketException, UnknownHostException {
        super();
        ds = new DatagramSocket(0xC939);
        dp = new DatagramPacket(sbuf, 11);
        dp_sts = new DatagramPacket(sbuf_sts, 6);
        dp.setAddress(InetAddress.getByName(host));
        dp.setPort(0xC93A);
        dp_sts.setAddress(InetAddress.getByName(host));
        dp_sts.setPort(0xC93A);
        this.ms_delay = ms_delay;
    }

    private byte nextID() {
        return ++id > 0xF
                ? id = 0
                : id;
    }

    public void shutdown() {
        this.process = false;
        try {
            this.join();
        } catch (InterruptedException ex) {
            Logger.getLogger(UDP_Fluder.class.getName()).log(Level.SEVERE, null, ex);
        }
        ds.close();
    }

    private void dataPacking(byte[] sbuf, int d1, int d2, int d3, long pos) {
        sbuf[1] = (byte) ((d1 >> 8) & 0xff);
        sbuf[2] = (byte) (d1 & 0xff);

        sbuf[3] = (byte) ((d2 >> 8) & 0xff);
        sbuf[4] = (byte) (d2 & 0xff);

        sbuf[5] = (byte) ((d3 >> 8) & 0xff);
        sbuf[6] = (byte) (d3 & 0xff);

        sbuf[7] = (byte) ((pos >> 24) & 0xff);
        sbuf[8] = (byte) ((pos >> 16) & 0xff);
        sbuf[9] = (byte) ((pos >> 8) & 0xff);
        sbuf[10] = (byte) (pos & 0xff);
    }

    private void updateBuffer() {
        sbuf[0] = (byte) (0x10 + nextID());
        pos++;

        /*dt1 = (int) (pos % 4096);
         dt2 = (int) (pos % 1000 + 2048);
         dt3 = (int) (pos % 2048 + 1000);*/

        dt1 = r.nextInt(4096);
        dt2 = r.nextInt(2048) + 1000;
        dt3 = r.nextInt(500) + 3500;

        dataPacking(sbuf, dt1, dt2, dt3, pos);

    }

    private void sendPacket() {

        updateBuffer();

        try {
            ds.send(dp);

        } catch (IOException ex) {
            Logger.getLogger(UDP_Fluder.class.getName()).log(Level.SEVERE, null, ex);
        }

    }

    private void sendPacketSts() {
        sbuf_sts[0] = (byte) (0x20 + nextID());
        try {
            ds.send(dp_sts);
        } catch (IOException ex) {
            Logger.getLogger(UDP_Fluder.class.getName()).log(Level.SEVERE, null, ex);
        }

    }

    public long getCntSend() {
        return cnt_send;
    }

    @Override
    public void run() {

        while (process) {

            if (r.nextInt(1000) != 999) {
                sendPacket();
                cnt_send++;
            } else {
                sendPacketSts();
                cnt_send_sts++;
            }
            try {
                Thread.sleep(ms_delay);
            } catch (InterruptedException ex) {
                Logger.getLogger(UDP_Fluder.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
    }
}
